package com.atguigu.gmall.common.service;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.entity.GmallCorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.UUID;

/**
 * 自定义实现类
 * 封装CorrelationData
 */
@SuppressWarnings("all")
@Component
public class RabbitService {

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisTemplate redisTemplate;

    //发消息 要求 发送失败后可以在应答处重新发送消息  要求有交换机 RoutingKey 消息 重发次数
    public void sendMessage(String exchange, String routingKey, Object msg) {
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        //用于队列应答 32位
        String uuid = UUID.randomUUID().toString().replace("-", "");
        //返回后uuid实质存在于message的messageProperties的headers中
        gmallCorrelationData.setId(uuid);
        //扩充 通过自定义CorrelationData的子类实现
        gmallCorrelationData.setExchange(exchange);
        gmallCorrelationData.setRoutingKey(routingKey);
        gmallCorrelationData.setMessage(msg);

        //Jackson转换需要序列化接口 JSONObject转换不需要序列化接口
        redisTemplate.opsForValue().set(uuid, JSONObject.toJSONString(gmallCorrelationData));
        //若发送失败后,将此gmallCorrelationData返回到应答处 目的是获取各种值以重新发送消息
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, gmallCorrelationData);
    }

    public void sendDeadLetterMessage(String exchange, String routingKey, Object msg, int ttl) {
        //关联数据的对象 为了交换机或队列应答失败
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        //用于队列应答 32位
        String uuid = UUID.randomUUID().toString().replace("-", "");
        //返回后uuid实质存在于message的messageProperties的headers中
        gmallCorrelationData.setId(uuid);
        //扩充 通过自定义CorrelationData的子类实现
        gmallCorrelationData.setExchange(exchange);
        gmallCorrelationData.setRoutingKey(routingKey);
        gmallCorrelationData.setMessage(msg);
        gmallCorrelationData.setDelay(true);
        gmallCorrelationData.setDelayTime(ttl);
        //Jackson转换需要序列化接口 JSONObject转换不需要序列化接口
        redisTemplate.opsForValue().set(uuid, JSONObject.toJSONString(gmallCorrelationData));
        //若发送失败后,将此correlationData返回到应答处 目的是获取各种值以重新发送消息
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, message -> {
            System.out.println("发送的延迟消息是:" + msg + ":时间:" + new Date());
            //发消息设置TTL和初始化TTL队列 都设置了存活时间,最终以时间少的为准
            //设置TTL的时间
            message.getMessageProperties().setExpiration(String.valueOf(ttl * 1000));
            return message;
        }, gmallCorrelationData);
    }

    //发送基于插件的延迟消息
    public void sendDelayedMessage(String exchange, String routingKey, Object msg, int delayTime) {
        //关联数据的对象 为了交换机或队列应答失败
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        //用于队列应答 32位
        String uuid = UUID.randomUUID().toString().replace("-", "");
        //返回后uuid实质存在于message的messageProperties的headers中
        gmallCorrelationData.setId(uuid);
        //扩充 通过自定义CorrelationData的子类实现
        gmallCorrelationData.setExchange(exchange);
        gmallCorrelationData.setRoutingKey(routingKey);
        gmallCorrelationData.setMessage(msg);
        gmallCorrelationData.setDelay(true);
        gmallCorrelationData.setDelayTime(delayTime);
        //若发送失败后,将此correlationData返回到应答处 目的是获取各种值以重新发送消息
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, message -> {
            System.out.println("发送的延迟消息是:" + msg + ":时间:" + new Date());
            //发消息设置TTL和初始化TTL队列 都设置了存活时间,最终以时间少的为准
            //设置TTL的时间
            message.getMessageProperties().setDelay(delayTime * 1000);//基于插件的延迟时间
            return message;
        }, gmallCorrelationData);
    }
}
